home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / DubStatus.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  22.5 KB  |  872 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include <windows.h>
  19. #include <commctrl.h>
  20. #include <crtdbg.h>
  21. #include <vfw.h>
  22.  
  23. #include "resource.h"
  24. #include "gui.h"
  25. #include "audio.h"
  26.  
  27. #include "AudioSource.h"
  28. #include "VideoSource.h"
  29. #include "InputFile.h"
  30.  
  31. #include "DubStatus.h"
  32.  
  33. #include "dub.h"
  34.  
  35. extern HWND g_hWnd;
  36.  
  37. ///////////////////////////////////////////////////////////////////////////
  38.  
  39. class DubStatus : public IDubStatusHandler {
  40. private:
  41.     enum { TITLE_IDLE, TITLE_MINIMIZED, TITLE_NORMAL };
  42.  
  43.     int                    iLastTitleMode;
  44.     long                lLastTitleProgress;
  45.  
  46.     HWND                hwndStatus;
  47.     UINT statTimer;
  48.     DWORD dwStartTime;
  49.     LONG lastFrame;
  50.     LONG lFrameDiff1,lFrameDiff2;
  51.     DWORD dwTicks, dwLastTicks1, dwLastTicks2;
  52.  
  53.     enum { MAX_FRAME_SIZES = 512 };
  54.  
  55.     DWORD        dwFrameSizes[MAX_FRAME_SIZES];
  56.     long        lFrameFirstIndex, lFrameLastIndex;
  57.     long        lFrameLobound, lFrameHibound;
  58.     RECT                rStatusChild;
  59.     HWND                hwndStatusChild;
  60.     bool                fShowStatusWindow;
  61.     bool                fFrozen;
  62.  
  63.     // our links...
  64.  
  65.     DubAudioStreamInfo    *painfo;
  66.     DubVideoStreamInfo    *pvinfo;
  67.     AudioSource            *aSrc;
  68.     VideoSource            *vSrc;
  69.     InputFile            *pInput;
  70.     AudioStream            *audioStreamSource;
  71.  
  72.     IDubber                *pDubber;
  73.     DubOptions            *opt;
  74.     DubPositionCallback    positionCallback;
  75.     int                    iPriority;                // current priority level index of processes
  76.  
  77.     static BOOL APIENTRY StatusMainDlgProc( HWND hWnd, UINT message, UINT wParam, LONG lParam );
  78.     static BOOL APIENTRY StatusVideoDlgProc( HWND hWnd, UINT message, UINT wParam, LONG lParam );
  79.     static BOOL APIENTRY StatusPerfDlgProc( HWND hWnd, UINT message, UINT wParam, LONG lParam );
  80.     static BOOL APIENTRY StatusDlgProc( HWND hWnd, UINT message, UINT wParam, LONG lParam );
  81.     void StatusTimerProc(HWND hWnd);
  82.  
  83.     static int iPriorities[][2];
  84.  
  85. public:
  86.     DubStatus();
  87.     ~DubStatus();
  88.     void InitLinks(    DubAudioStreamInfo    *painfo,
  89.         DubVideoStreamInfo    *pvinfo,
  90.         AudioSource            *aSrc,
  91.         VideoSource            *vSrc,
  92.         InputFile            *pInput,
  93.         AudioStream            *audioStreamSource,
  94.  
  95.         IDubber                *pDubber,
  96.         DubOptions            *opt);
  97.     HWND Display(HWND hwndParent, int iInitialPriority);
  98.     void Destroy();
  99.     bool ToggleStatus();
  100.     void SetPositionCallback(DubPositionCallback dpc);
  101.     void NotifyNewFrame(long f);
  102.     void SetLastPosition(LONG pos);
  103.     void Freeze();
  104.     bool isVisible();
  105.     bool isFrameVisible(bool fOutput);
  106.     bool ToggleFrame(bool fOutput);
  107.  
  108. };
  109.  
  110. IDubStatusHandler *CreateDubStatusHandler() {
  111.     return new DubStatus();
  112. }
  113.  
  114. ///////////////////////////////////////////////////////////////////////////
  115.  
  116. extern char g_szInputAVIFileTitle[];
  117. extern HINSTANCE g_hInst;
  118. extern HWND g_hWnd;
  119.  
  120. ///////////////////////////////////////////////////////////////////////////
  121.  
  122. static long pickClosestNiceBound(long val, bool higher) {
  123.  
  124.     static long bounds[]={
  125.         0,
  126.         100,
  127.         200,
  128.         500,
  129.         1024,
  130.         2048,
  131.         5120,
  132.         10240,
  133.         20480,
  134.         51200,
  135.         102400,
  136.         204800,
  137.         512000,
  138.         1048576,
  139.         2097152,
  140.         5242880,
  141.         10485760,
  142.         20971520,
  143.         52428800,
  144.         104857600,
  145.         209715200,
  146.         524288000,
  147.         1073741824,
  148.         2147483647,
  149.     };
  150.  
  151.     int i;
  152.  
  153.     // silly value?
  154.  
  155.     if (val <= 0)
  156.         return 0;
  157.  
  158.     if (!higher) {
  159.         for(i=0; i<23; i++)
  160.             if (bounds[i] <= val)
  161.                 return bounds[i];
  162.  
  163.         return 0x7FFFFFFF;
  164.     } else {
  165.         for(i=23; i>0; i--)
  166.             if (bounds[i-1] < val)
  167.                 break;
  168.  
  169.         return bounds[i];
  170.     }
  171. }
  172.  
  173. ///////////////////////////////////////////////////////////////////////////
  174.  
  175. DubStatus::DubStatus() {
  176.     iLastTitleMode        = TITLE_IDLE;
  177.     lLastTitleProgress    = 0;
  178.  
  179.     memset(dwFrameSizes, 0, sizeof dwFrameSizes);
  180.     lFrameFirstIndex = 0;
  181.     lFrameLastIndex = 0;
  182.  
  183.     fShowStatusWindow    = true;
  184.  
  185.     hwndStatus            = NULL;
  186.     positionCallback    = NULL;
  187.  
  188.     fFrozen = false;
  189. }
  190.  
  191. DubStatus::~DubStatus() {
  192.     Destroy();
  193. }
  194.  
  195. void DubStatus::InitLinks(    DubAudioStreamInfo    *painfo,
  196.     DubVideoStreamInfo    *pvinfo,
  197.     AudioSource            *aSrc,
  198.     VideoSource            *vSrc,
  199.     InputFile            *pInput,
  200.     AudioStream            *audioStreamSource,
  201.  
  202.     IDubber                *pDubber,
  203.     DubOptions            *opt) {
  204.  
  205.     this->painfo            = painfo;
  206.     this->pvinfo            = pvinfo;
  207.     this->aSrc                = aSrc;
  208.     this->vSrc                = vSrc;
  209.     this->pInput            = pInput;
  210.     this->audioStreamSource    = audioStreamSource;
  211.  
  212.     this->pDubber            = pDubber;
  213.     this->opt                = opt;
  214.  
  215.     if (!GetWindowLong(g_hWnd, GWL_USERDATA))
  216.         DestroyWindow(g_hWnd);
  217. }
  218.  
  219.  
  220. HWND DubStatus::Display(HWND hwndParent, int iInitialPriority) {
  221.     iPriority = iInitialPriority;
  222.  
  223.     if (hwndStatus = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_DUBBING), hwndParent, StatusDlgProc, (LPARAM)this)) {
  224.         if (fShowStatusWindow = opt->fShowStatus) {
  225.             SetWindowLong(hwndStatus, GWL_STYLE, GetWindowLong(hwndStatus, GWL_STYLE) & ~WS_POPUP);
  226.             ShowWindow(hwndStatus, SW_SHOW);
  227.         }
  228.  
  229.         return hwndStatus;
  230.     }
  231.     return NULL;
  232. }
  233.  
  234. void DubStatus::Destroy() {
  235.     if (hwndStatus) {
  236.         DestroyWindow(hwndStatus);
  237.         hwndStatus = NULL;
  238.     }
  239. }
  240.  
  241.  
  242. ///////////////////////////////////////////////////////////////////////////
  243.  
  244. void DubStatus::StatusTimerProc(HWND hWnd) {
  245.     DWORD dwProgress;
  246.     __int64 lProjSize;
  247.     char buf[256];
  248.  
  249.     LONG    totalVSamples    = pvinfo->end_src - pvinfo->start_src;
  250. //    LONG    totalASamples    = painfo->end_src - painfo->start_src;
  251.     LONG    totalASamples    = audioStreamSource ? audioStreamSource->GetLength() : 0;
  252.     LONG    curVSample        = pvinfo->cur_proc_src - pvinfo->start_src;
  253.     LONG    curASample        = audioStreamSource ? audioStreamSource->GetSampleCount() : 0;
  254.     char    *s;
  255.  
  256.     /////////////
  257.  
  258.     dwProgress = (curVSample>totalVSamples ? 4096 : MulDiv(curVSample, 4096, totalVSamples))
  259.                 +(curASample>totalASamples ? 4096 : MulDiv(curASample, 4096, totalASamples));
  260.  
  261.     if (!totalASamples || !totalVSamples || pvinfo->fAudioOnly) dwProgress *= 2;
  262.  
  263.     dwLastTicks2 = dwLastTicks1;
  264.     dwLastTicks1 = dwTicks;
  265.     dwTicks = GetTickCount() - dwStartTime;
  266.  
  267.     wsprintf(buf, "%ld/%ld", curVSample, totalVSamples);
  268.     SetDlgItemText(hWnd, IDC_CURRENT_VFRAME, buf);
  269.  
  270.     wsprintf(buf, "%ld/%ld", curASample, totalASamples);
  271.     SetDlgItemText(hWnd, IDC_CURRENT_ASAMPLE, buf);
  272.  
  273.     size_to_str(buf, pvinfo->total_size);
  274.  
  275.     if (pvinfo->processed) {
  276.         __int64 divisor = pvinfo->processed*(__int64)pvinfo->usPerFrame;
  277.  
  278.         s=buf; while(*s) ++s;
  279.         wsprintf(s, " (%3ldK/s)", (long)((((pvinfo->total_size+1023)/1024)*1000000i64 + divisor - 1) / divisor));
  280.     }
  281.  
  282.     SetDlgItemText(hWnd, IDC_CURRENT_VSIZE, buf);
  283.  
  284.     size_to_str(buf, painfo->total_size);
  285.     SetDlgItemText(hWnd, IDC_CURRENT_ASIZE, buf);
  286.  
  287.     lProjSize = 0;
  288.     if (totalVSamples && curVSample) {
  289.         long divisor = min(totalVSamples, curVSample);
  290.  
  291.         lProjSize += ((__int64)pvinfo->total_size * totalVSamples + divisor/2) / divisor;
  292.     }
  293.     if (totalASamples && curASample) {
  294.         __int64 divisor = (__int64)min(totalASamples, curASample);// * wf->nSamplesPerSec;
  295.  
  296.         lProjSize += ((__int64)painfo->total_size * 
  297.                         (__int64)totalASamples + divisor/2) / divisor;
  298.     }
  299.  
  300.     if (lProjSize) {
  301.         lProjSize += 2048 + 16;
  302.  
  303.         __int64 kilobytes = (lProjSize+1023)>>10;
  304.  
  305.         if (kilobytes < 65536)
  306.             wsprintf(buf, "%ldK", kilobytes);
  307.         else {
  308.             kilobytes = (lProjSize*100) / 1048576;
  309.             wsprintf(buf, "%ld.%02dMb", (LONG)(kilobytes/100), (LONG)(kilobytes%100));
  310.         }
  311.         SetDlgItemText(hWnd, IDC_PROJECTED_FSIZE, buf);
  312.     } else {
  313.         SetDlgItemText(hWnd, IDC_PROJECTED_FSIZE, "unknown");
  314.     }
  315.  
  316.     ticks_to_str(buf, dwTicks);
  317.     SetDlgItemText(hWnd, IDC_TIME_ELAPSED, buf);
  318.  
  319.     if (dwProgress > 16) {
  320.         ticks_to_str(buf, MulDiv(dwTicks,8192,dwProgress));
  321.         SetDlgItemText(hWnd, IDC_TIME_REMAINING, buf);
  322.     }
  323.  
  324.     lFrameDiff2 = lFrameDiff1;
  325.     lFrameDiff1 = pvinfo->processed-lastFrame;
  326.     lastFrame += lFrameDiff1;
  327.  
  328.     {
  329.         long fps10;
  330.  
  331.         fps10 = MulDiv(lFrameDiff1 + lFrameDiff2, 10000, dwTicks - dwLastTicks2);
  332.  
  333.         wsprintf(buf, "%ld.%c fps",fps10/10, (fps10%10) + '0');
  334.         SetDlgItemText(hWnd, IDC_FPS, buf);
  335.     }
  336.  
  337.     if (GetWindowLong(g_hWnd, GWL_STYLE) & WS_MINIMIZE) {
  338.         long lNewProgress = (dwProgress*25)/2048;
  339.  
  340.         if (iLastTitleMode != TITLE_MINIMIZED || lLastTitleProgress != lNewProgress) {
  341.             guiSetTitle(g_hWnd, IDS_TITLE_DUBBING_MINIMIZED, lNewProgress, g_szInputAVIFileTitle);
  342.  
  343.             iLastTitleMode = TITLE_MINIMIZED;
  344.             lLastTitleProgress = lNewProgress;
  345.         }
  346.     } else {
  347.         if (iLastTitleMode != TITLE_NORMAL) {
  348.             iLastTitleMode = TITLE_NORMAL;
  349.             guiSetTitle(g_hWnd, IDS_TITLE_DUBBING, g_szInputAVIFileTitle);
  350.         }
  351.     }
  352. }
  353.  
  354. ///////////////////////////////////
  355.  
  356. BOOL APIENTRY DubStatus::StatusMainDlgProc( HWND hdlg, UINT message, UINT wParam, LONG lParam) {
  357.     DubStatus *thisPtr = (DubStatus *)GetWindowLong(hdlg, DWL_USER);
  358.  
  359.     switch (message)
  360.     {
  361.         case WM_INITDIALOG:
  362.             {
  363.                 SetWindowLong(hdlg, DWL_USER, lParam);
  364.                 thisPtr = (DubStatus *)lParam;
  365.                 SetWindowPos(hdlg, HWND_TOP, thisPtr->rStatusChild.left, thisPtr->rStatusChild.top, 0, 0, SWP_NOSIZE);
  366.  
  367.                 thisPtr->StatusTimerProc(hdlg);
  368.             }
  369.             return (TRUE);
  370.  
  371.         case WM_TIMER:
  372.             thisPtr->StatusTimerProc(hdlg);
  373.             return TRUE;
  374.  
  375.     }
  376.     return FALSE;
  377. }
  378.  
  379.  
  380.  
  381. BOOL APIENTRY DubStatus::StatusVideoDlgProc( HWND hdlg, UINT message, UINT wParam, LONG lParam) {
  382.     DubStatus *thisPtr = (DubStatus *)GetWindowLong(hdlg, DWL_USER);
  383.  
  384.     switch (message)
  385.     {
  386.         case WM_INITDIALOG:
  387.             {
  388.                 SetWindowLong(hdlg, DWL_USER, lParam);
  389.                 thisPtr = (DubStatus *)lParam;
  390.                 SetWindowPos(hdlg, HWND_TOP, thisPtr->rStatusChild.left, thisPtr->rStatusChild.top, 0, 0, SWP_NOSIZE);
  391.  
  392.                 thisPtr->lFrameLobound = 0;
  393.                 thisPtr->lFrameHibound = 10240;
  394.             }
  395.             return (TRUE);
  396.  
  397.         case WM_TIMER:
  398.             {
  399.                 HDC hdc;
  400.                 RECT r;
  401.                 RECT rUpdate;
  402.                 int dx;
  403.  
  404.                 dx = thisPtr->lFrameLastIndex - thisPtr->lFrameFirstIndex;
  405.  
  406.                 if (dx > 0) {
  407.                     long lo, hi;
  408.                     int i;
  409.  
  410.                     r.left = r.top = 7;
  411.                     r.right = 7 + 133;
  412.                     r.bottom = 7 + 72;
  413.  
  414.                     MapDialogRect(hdlg, &r);
  415.  
  416.                     // scan the array and recompute bounds
  417.  
  418.                     lo = 0x7FFFFFFF;
  419.                     hi = 0;
  420.  
  421.                     for(i=r.left - r.right; i<0; i++) {
  422.                         if (thisPtr->lFrameFirstIndex + i >= 0) {
  423.                             long size = thisPtr->dwFrameSizes[(thisPtr->lFrameFirstIndex+i) & (MAX_FRAME_SIZES-1)] & 0x7FFFFFFF;
  424.  
  425.                             if (size < lo)
  426.                                 lo = size;
  427.  
  428.                             if (size > hi)
  429.                                 hi = size;
  430.                         }
  431.                     }
  432.  
  433.                     // compute "nice" bounds
  434.  
  435.                     if (lo == 0x7FFFFFFF)
  436.                         lo = 0;
  437.  
  438.                     lo = pickClosestNiceBound(lo, false);
  439.                     hi = pickClosestNiceBound(hi, true);
  440.  
  441.                     if (lo == hi)
  442.                         hi = pickClosestNiceBound(hi+1, true);
  443.  
  444.                     // if the bounds are different, force a full redraw, else scroll
  445.  
  446.                     thisPtr->lFrameFirstIndex += dx;
  447.                     if (lo != thisPtr->lFrameLobound || hi != thisPtr->lFrameHibound) {
  448.                         char buf[64];
  449.  
  450.                         thisPtr->lFrameLobound = lo;
  451.                         thisPtr->lFrameHibound = hi;
  452.  
  453.                         if (lo >= 0x40000000)
  454.                             wsprintf(buf, "%dGb", lo>>30);
  455.                         else if (lo >= 0x100000)
  456.                             wsprintf(buf, "%dMb", lo>>20);
  457.                         else if (lo >= 0x400)
  458.                             wsprintf(buf, "%dK", lo>>10);
  459.                         else
  460.                             wsprintf(buf, "%d", lo);
  461.                         SetDlgItemText(hdlg, IDC_STATIC_LOBOUND, buf);
  462.  
  463.                         if (hi >= 0x40000000)
  464.                             wsprintf(buf, "%dGb", hi>>30);
  465.                         else if (hi >= 0x100000)
  466.                             wsprintf(buf, "%dMb", hi>>20);
  467.                         else if (hi >= 0x400)
  468.                             wsprintf(buf, "%dK", hi>>10);
  469.                         else
  470.                             wsprintf(buf, "%d", hi);
  471.                         SetDlgItemText(hdlg, IDC_STATIC_HIBOUND, buf);
  472.  
  473.                         InvalidateRect(hdlg, &r, FALSE);
  474.                     } else if (hdc = GetDC(hdlg)) {
  475.  
  476.                         ScrollDC(hdc, -dx, 0, &r, &r, NULL, &rUpdate);
  477.  
  478.                         rUpdate.left = r.right - dx;
  479.                         rUpdate.right = r.right;
  480.                         rUpdate.top = r.top;
  481.                         rUpdate.bottom = r.bottom;
  482.  
  483.                         InvalidateRect(hdlg, &rUpdate, FALSE);
  484.  
  485.                         ReleaseDC(hdlg, hdc);
  486.                     }
  487.                 }
  488.  
  489.             }
  490.             return TRUE;
  491.  
  492.         case WM_PAINT:
  493.             {
  494.                 PAINTSTRUCT ps;
  495.                 HDC hdc;
  496.                 RECT r, r2;
  497.                 RECT rDest;
  498.                 HBRUSH hbrRed, hbrBlue;
  499.                 int x, width, height;
  500.                 long range = thisPtr->lFrameHibound - thisPtr->lFrameLobound;
  501.  
  502.                 if (!range) ++range;
  503.  
  504.                 r.left = r.top = 7;
  505.                 r.right = 7+133;
  506.                 r.bottom = 72;
  507.  
  508.                 MapDialogRect(hdlg, &r);
  509.  
  510.                 width = r.right - r.left;
  511.                 height = r.bottom - r.top;
  512.  
  513.                 hdc = BeginPaint(hdlg, &ps);
  514.  
  515.                 IntersectRect(&rDest, &r, &ps.rcPaint);
  516.  
  517.                 FillRect(hdc, &rDest, (HBRUSH)GetStockObject(BLACK_BRUSH));
  518.  
  519.                 hbrRed = CreateSolidBrush(RGB(255,0,0));
  520.                 hbrBlue = CreateSolidBrush(RGB(0,0,255));
  521.  
  522.                 for(x=rDest.left; x<rDest.right; x++) {
  523.                     DWORD dwSize;
  524.                     int y;
  525.  
  526.                     if (thisPtr->lFrameFirstIndex+x-r.right >= 0) {
  527.                         dwSize = thisPtr->dwFrameSizes[(thisPtr->lFrameFirstIndex+x-r.right) & (MAX_FRAME_SIZES-1)];
  528.  
  529.                         y = (((dwSize & 0x7FFFFFFF) - thisPtr->lFrameLobound)*height + range - 1)/range;
  530.                         if (y > height)
  531.                             y = height;
  532.  
  533.                         if (y>0) {
  534.  
  535.                             r2.left = x;
  536.                             r2.right = x+1;
  537.                             r2.top = r.bottom - y;
  538.                             r2.bottom = r.bottom;
  539.  
  540.                             FillRect(hdc, &r2, dwSize & 0x80000000 ? hbrBlue : hbrRed);
  541.                         }
  542.                     }
  543.                 }
  544.  
  545.                 DeleteObject(hbrBlue);
  546.                 DeleteObject(hbrRed);
  547.  
  548.                 EndPaint(hdlg, &ps);
  549.             }
  550.             return TRUE;
  551.  
  552.     }
  553.     return FALSE;
  554. }
  555.  
  556. BOOL APIENTRY DubStatus::StatusPerfDlgProc( HWND hdlg, UINT message, UINT wParam, LONG lParam) {
  557.     DubStatus *thisPtr = (DubStatus *)GetWindowLong(hdlg, DWL_USER);
  558.  
  559.     switch (message)
  560.     {
  561.         case WM_INITDIALOG:
  562.             {
  563.                 SetWindowLong(hdlg, DWL_USER, lParam);
  564.                 thisPtr = (DubStatus *)lParam;
  565.                 SetWindowPos(hdlg, HWND_TOP, thisPtr->rStatusChild.left, thisPtr->rStatusChild.top, 0, 0, SWP_NOSIZE);
  566.  
  567.             }
  568.             return (TRUE);
  569.  
  570.         case WM_TIMER:
  571.             if (thisPtr->pInput) {
  572.                 SetDlgItemText(hdlg, IDC_STATIC_OPTPREVIEW,
  573.                     thisPtr->pInput->isOptimizedForRealtime() ? "Yes" : "No");
  574.  
  575.                 SetDlgItemText(hdlg, IDC_STATIC_READMODE,
  576.                     thisPtr->pInput->isStreaming() ? "Streaming" : "Discrete");
  577.  
  578.                 if (thisPtr->vSrc)
  579.                     SetDlgItemText(hdlg, IDC_STATIC_VIDEOSTREAM,
  580.                         thisPtr->vSrc->isStreaming() ? "Yes" : "No");
  581.  
  582.                 if (thisPtr->aSrc)
  583.                     SetDlgItemText(hdlg, IDC_STATIC_AUDIOSTREAM,
  584.                         thisPtr->aSrc->isStreaming() ? "Yes" : "No");
  585.             }
  586.             return TRUE;
  587.  
  588.     }
  589.     return FALSE;
  590. }
  591.  
  592. ///////////////////////////////////
  593.  
  594. const char * const g_szDubPriorities[]={
  595.         "Idle",
  596.         "Lowest",
  597.         "Even lower",
  598.         "Lower",
  599.         "Normal",
  600.         "Higher",
  601.         "Even higher",
  602.         "Highest",
  603. };
  604.  
  605. BOOL APIENTRY DubStatus::StatusDlgProc( HWND hdlg, UINT message, UINT wParam, LONG lParam) {
  606.  
  607.     static struct DubStatusTabs {
  608.         LPTSTR    rsrc;
  609.         char    *name;
  610.         DLGPROC    dProc;
  611.     } tabs[]={
  612.         {    MAKEINTRESOURCE(IDD_DUBBING_MAIN),    "Main",        StatusMainDlgProc    },
  613.         {    MAKEINTRESOURCE(IDD_DUBBING_VIDEO),    "Video",    StatusVideoDlgProc    },
  614.         {    MAKEINTRESOURCE(IDD_DUBBING_PERF),    "Perf",        StatusPerfDlgProc    },
  615.     };
  616.  
  617.     DubStatus *thisPtr = (DubStatus *)GetWindowLong(hdlg, DWL_USER);
  618.     HWND hwndItem;
  619.     RECT r, r2;
  620.     int i;
  621.  
  622. #define MYWM_NULL (WM_APP + 0)
  623.  
  624.     switch (message)
  625.     {
  626.         case WM_INITDIALOG:
  627.             {
  628.                 long xoffset, yoffset;
  629.  
  630.                 SetWindowLong(hdlg, DWL_USER, lParam);
  631.                 thisPtr = (DubStatus *)lParam;
  632.  
  633.                 thisPtr->hwndStatus = hdlg;
  634.  
  635.                 // Initialize tab window
  636.  
  637.                 hwndItem = GetDlgItem(hdlg, IDC_TABS);
  638.  
  639.                 for(i=0; i<(sizeof tabs/sizeof tabs[0]); i++) {
  640.                     TC_ITEM ti;
  641.  
  642.                     ti.mask        = TCIF_TEXT;
  643.                     ti.pszText    = tabs[i].name;
  644.  
  645.                     TabCtrl_InsertItem(hwndItem, i, &ti);
  646.                 }
  647.  
  648.                 // Compute size of tab control needed to hold this child dialog
  649.  
  650.                 r.left = r.top = 0;
  651.                 r.right = 172;
  652.                 r.bottom = 102;
  653.                 MapDialogRect(hdlg, &r);
  654.  
  655.                 TabCtrl_AdjustRect(hwndItem, TRUE, &r);
  656.  
  657.                 // Resize tab control and compute offsets for other controls
  658.  
  659.                 GetWindowRect(hwndItem, &r2);
  660.                 ScreenToClient(hdlg, (LPPOINT)&r2 + 0);
  661.                 ScreenToClient(hdlg, (LPPOINT)&r2 + 1);
  662.  
  663.                 OffsetRect(&r, r2.left - r.left, r2.top - r.top);
  664.  
  665.                 SetWindowPos(hwndItem, NULL, r.left, r.top, r.right-r.left, r.bottom-r.top, SWP_NOZORDER);
  666.                 thisPtr->rStatusChild = r;
  667.  
  668.                 TabCtrl_AdjustRect(hwndItem, FALSE, &thisPtr->rStatusChild);
  669.  
  670.                 xoffset = (r.right-r.left) - (r2.right-r2.left);
  671.                 yoffset = (r.bottom-r.top) - (r2.bottom-r2.top);
  672.  
  673.                 guiResizeDlgItem(hdlg, IDC_PROGRESS, 0, yoffset, xoffset, 0);
  674.                 guiResizeDlgItem(hdlg, IDC_PRIORITY, 0, yoffset, xoffset, 0);
  675.                 guiOffsetDlgItem(hdlg, IDC_ABORT, xoffset, yoffset);
  676.                 guiOffsetDlgItem(hdlg, IDC_STATIC_PROGRESS, 0, yoffset);
  677.                 guiOffsetDlgItem(hdlg, IDC_STATIC_PRIORITY, 0, yoffset);
  678.                 guiOffsetDlgItem(hdlg, IDC_DRAW_INPUT, 0, yoffset);
  679.                 guiOffsetDlgItem(hdlg, IDC_DRAW_OUTPUT, 0, yoffset);
  680.  
  681.                 // resize us
  682.  
  683.                 GetWindowRect(hdlg, &r);
  684.                 SetWindowPos(hdlg, NULL, 0, 0, r.right-r.left + xoffset, r.bottom-r.top + yoffset, SWP_NOMOVE | SWP_NOZORDER);
  685.  
  686.                 // open up child dialog
  687.  
  688.                 thisPtr->hwndStatusChild = CreateDialogParam(g_hInst, tabs[0].rsrc, hdlg, tabs[0].dProc, (LPARAM)thisPtr);
  689.  
  690.                 // setup timer, progress bar
  691.  
  692.                 thisPtr->statTimer = SetTimer(hdlg, 1, 500, NULL);
  693.                 SendMessage(GetDlgItem(hdlg, IDC_PROGRESS), PBM_SETRANGE, 0, MAKELPARAM(0, 8192));
  694.                 thisPtr->dwStartTime    = GetTickCount();
  695.                 thisPtr->lastFrame        = 0;
  696.                 thisPtr->lFrameDiff1    = 0;
  697.                 thisPtr->dwTicks        = 0;
  698.                 thisPtr->dwLastTicks1    = 0;
  699.  
  700.                 CheckDlgButton(hdlg, IDC_DRAW_INPUT, thisPtr->opt->video.fShowInputFrame);
  701.                 CheckDlgButton(hdlg, IDC_DRAW_OUTPUT, thisPtr->opt->video.fShowOutputFrame);
  702.  
  703.                 hwndItem = GetDlgItem(hdlg, IDC_PRIORITY);
  704.                 SendMessage(hwndItem, CB_RESETCONTENT,0,0);
  705.                 for(i=0; i<8; i++)
  706.                     SendMessage(hwndItem, CB_ADDSTRING, 0, (LPARAM)g_szDubPriorities[i]);
  707.  
  708.                 SendMessage(hwndItem, CB_SETCURSEL, thisPtr->iPriority-1, 0);
  709.  
  710.                 guiSetTitle(hdlg, IDS_TITLE_STATUS,  g_szInputAVIFileTitle);
  711.  
  712.             }
  713.             return (TRUE);
  714.  
  715.         case WM_DESTROY:
  716.             thisPtr->hwndStatus = NULL;
  717.             if (thisPtr->statTimer)
  718.                 KillTimer(hdlg, thisPtr->statTimer);
  719.             PostMessage(GetParent(hdlg), MYWM_NULL, 0, 0);
  720.             return TRUE;
  721.  
  722.         case WM_TIMER:
  723.             if (thisPtr->fFrozen)
  724.                 return TRUE;
  725.  
  726.             thisPtr->SetLastPosition(thisPtr->pvinfo->cur_proc_src);
  727.  
  728.             if (thisPtr->hwndStatusChild)
  729.                 SendMessage(thisPtr->hwndStatusChild, WM_TIMER, 0, 0);
  730.  
  731.             {
  732.                 DWORD dwProgress;
  733.  
  734.                 LONG    totalVSamples    = thisPtr->pvinfo->end_src - thisPtr->pvinfo->start_src;
  735.                 LONG    totalASamples    = thisPtr->audioStreamSource ? thisPtr->audioStreamSource->GetLength() : 0;
  736. //                LONG    totalASamples    = thisPtr->painfo->end_src - thisPtr->painfo->start_src;
  737.                 LONG    curVSample        = thisPtr->pvinfo->cur_proc_src - thisPtr->pvinfo->start_src;
  738.                 LONG    curASample        = thisPtr->audioStreamSource ? thisPtr->audioStreamSource->GetSampleCount() : 0;
  739.  
  740.                 /////////////
  741.  
  742.                 dwProgress = (curVSample>totalVSamples ? 4096 : MulDiv(curVSample, 4096, totalVSamples))
  743.                             +(curASample>totalASamples ? 4096 : MulDiv(curASample, 4096, totalASamples));
  744.  
  745.                 if (!totalASamples || !totalVSamples || thisPtr->pvinfo->fAudioOnly) dwProgress *= 2;
  746.  
  747.                 SendMessage(GetDlgItem(hdlg, IDC_PROGRESS), PBM_SETPOS,    (WPARAM)dwProgress, 0);
  748.             }
  749.  
  750.             thisPtr->pDubber->UpdateFrames();
  751.  
  752.             return TRUE;
  753.  
  754.         case WM_NOTIFY: {
  755.             NMHDR *nm = (LPNMHDR)lParam;
  756.  
  757.             switch(nm->code) {
  758.             case TCN_SELCHANGE:
  759.                 {
  760.                     int iTab = TabCtrl_GetCurSel(nm->hwndFrom);
  761.  
  762.                     if (iTab>=0) {
  763.                         if (thisPtr->hwndStatusChild)
  764.                             DestroyWindow(thisPtr->hwndStatusChild);
  765.  
  766.                         thisPtr->hwndStatusChild = CreateDialogParam(g_hInst, tabs[iTab].rsrc, hdlg, tabs[iTab].dProc, (LPARAM)thisPtr);
  767.                     }
  768.                 }
  769.                 return TRUE;
  770.             }
  771.             }break;
  772.  
  773.         case WM_COMMAND:                      
  774.             switch(LOWORD(wParam)) {
  775.             case IDC_DRAW_INPUT:
  776.                 thisPtr->opt->video.fShowInputFrame = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0)==BST_CHECKED;
  777.                 break;
  778.  
  779.             case IDC_DRAW_OUTPUT:
  780.                 thisPtr->opt->video.fShowOutputFrame = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0)==BST_CHECKED;
  781.                 break;
  782.  
  783.             case IDC_PRIORITY:
  784.                 if (HIWORD(wParam) == CBN_SELCHANGE) {
  785.                     LRESULT index;
  786.  
  787.                     if (CB_ERR != (index = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0))) {
  788.                         thisPtr->pDubber->SetPriority(index);
  789.                     }
  790.                 }
  791.                 break;
  792.  
  793.             case IDC_ABORT:
  794.                 SendMessage(hdlg, WM_SETTEXT, 0, (LPARAM)"Aborting...");
  795.                 EnableWindow((HWND)lParam, FALSE);
  796.                 thisPtr->pDubber->Abort();
  797.                 thisPtr->hwndStatus = NULL;
  798.                 DestroyWindow(hdlg);
  799.                 break;
  800.  
  801.             case IDCANCEL:
  802.                 _RPT0(0,"Received cancel\n");
  803.                 thisPtr->ToggleStatus();
  804.                 break;
  805.             }
  806.             break;
  807.     }
  808.     return FALSE;
  809. }
  810.  
  811.  
  812. bool DubStatus::ToggleStatus() {
  813.  
  814.     fShowStatusWindow = !fShowStatusWindow;
  815.  
  816.     if (hwndStatus) {
  817.         if (fShowStatusWindow) {
  818.             SetWindowLong(hwndStatus, GWL_STYLE, GetWindowLong(hwndStatus, GWL_STYLE) & ~WS_POPUP);
  819.             ShowWindow(hwndStatus, SW_SHOW);
  820.         } else {
  821.             SetWindowLong(hwndStatus, GWL_STYLE, GetWindowLong(hwndStatus, GWL_STYLE) | WS_POPUP);
  822.             ShowWindow(hwndStatus, SW_HIDE);
  823.         }
  824.     }
  825.  
  826.     return fShowStatusWindow;
  827. }
  828.  
  829. void DubStatus::SetPositionCallback(DubPositionCallback dpc) {
  830.     positionCallback = dpc;
  831. }
  832.  
  833. void DubStatus::NotifyNewFrame(long f) {
  834.     dwFrameSizes[(lFrameLastIndex++)&(MAX_FRAME_SIZES-1)] = (DWORD)f;
  835. }
  836.  
  837. void DubStatus::SetLastPosition(LONG pos) {
  838.         if (positionCallback)
  839.             positionCallback(
  840.                     pvinfo->start_src,
  841.                     pos < pvinfo->start_src
  842.                             ? pvinfo->start_src
  843.                             : pos > pvinfo->end_src
  844.                                     ? pvinfo->end_src
  845.                                     : pos,
  846.                     pvinfo->end_src);
  847. }
  848.  
  849. void DubStatus::Freeze() {
  850.     fFrozen = true;
  851. }
  852.  
  853. bool DubStatus::isVisible() {
  854.     return fShowStatusWindow;
  855. }
  856.  
  857. bool DubStatus::isFrameVisible(bool fOutput) {
  858.     return !!(fOutput ? opt->video.fShowOutputFrame : opt->video.fShowInputFrame);
  859. }
  860.  
  861. bool DubStatus::ToggleFrame(bool fFrameOutput) {
  862.     if (fFrameOutput) {
  863.         if (hwndStatus)
  864.             PostMessage(GetDlgItem(hwndStatus, IDC_DRAW_OUTPUT), BM_SETCHECK, !opt->video.fShowOutputFrame ? BST_CHECKED : BST_UNCHECKED, 0);
  865.         return opt->video.fShowOutputFrame = !opt->video.fShowOutputFrame;
  866.     } else {
  867.         if (hwndStatus)
  868.             PostMessage(GetDlgItem(hwndStatus, IDC_DRAW_INPUT), BM_SETCHECK, !opt->video.fShowInputFrame ? BST_CHECKED : BST_UNCHECKED, 0);
  869.         return opt->video.fShowInputFrame = !opt->video.fShowInputFrame;
  870.     }
  871. }
  872.